<?php
namespace App\Logic\Storage;

use App\Logic\Basics\SerialNo;
use App\Models\Basics\Account;
use App\Models\Product\ProductSku;
use App\Models\Storage\CountryInventory;
use App\Models\Storage\RecordInventory;
use Illuminate\Support\Facades\DB;
class MixInventory
{
    public static function init(){
        try{
            $ps = ProductSku::where('is_once',1)
                ->where('is_mix',1)
                ->whereNotIn('psku_id',[499,498,495,364,363,353,352,351,1247,1246,1245,1244,493,492,491,490])
                ->where('psku_status','<>',3)
                ->get();
            $i = 0;
            $num = 100;
            while(true){
                if($ps->isEmpty())break;
                $_ps = $ps->splice($i,$num);
                DB::beginTransaction();
                foreach($_ps as $item){
                    $mixRuleArr = ProductSku::splitMixSku($item->mix_rule);
                    $mixNum = self::_mixSku($mixRuleArr);
                    if(!$mixNum)continue;
                    $count = CountryInventory::where('country_id',Account::PUBLIC_COUNTRY)->where('psku_id',$item->id)->count();
                    if($count == 0){
                        CountryInventory::create(['country_id' => Account::PUBLIC_COUNTRY,'psku_id' => $item->id,'seller_id' => Account::N_COUNTRY]);
                    }
                    $ci = CountryInventory::where('country_id',Account::PUBLIC_COUNTRY)
                        ->where('psku_id',$item->id)
                        ->lockForUpdate()
                        ->first();
                    if(!$ci)continue;
                    $isTrue = true;
                    $recordNo = SerialNo::getRcNo();
                    foreach($mixRuleArr as $_pSkuId => $_num){
                        $instantNum = $_num * $mixNum;
                        $pci = CountryInventory::where([['country_id',Account::PUBLIC_COUNTRY],['psku_id',$_pSkuId]])->lockForUpdate()->first();
                        $_tempInstantNum = $pci->instant_num ?? 0;
                        if($_tempInstantNum < $instantNum){
                            $isTrue = false;
                            break;
                        }
                        $pci->instant_num -= $instantNum;
                        $pci->save();
                        RecordInventory::create([
                            'record_no' => $recordNo,
                            'a_type' => 2,
                            'r_type' => 2,
                            'country_id' => Account::PUBLIC_COUNTRY,
                            'psku_id' => $_pSkuId,
                            'num' => -$instantNum,
                            'user_id' => 1
                        ]);
                    }
                    if($isTrue){
                        $ci->instant_num += $mixNum;
                        $ci->save();
                        RecordInventory::create([
                            'record_no' => $recordNo,
                            'a_type' => 2,
                            'r_type' => 1,
                            'country_id' => Account::PUBLIC_COUNTRY,
                            'psku_id' => $item->id,
                            'num' => $mixNum,
                            'user_id' => 1
                        ]);
                        DB::commit();
                    }else{
                        DB::rollBack();
                    }
                }
            }
        }catch (\Exception $e){
            DB::rollBack();
        }
    }

    private static function _mixSku($mixRuleArr){
        $cis = CountryInventory::whereIn('psku_id',array_keys($mixRuleArr))
            ->where('country_id',Account::PUBLIC_COUNTRY)
            ->pluck('instant_num','psku_id')
            ->toArray();
        if(empty($cis)) return 0;
        $re = [];
        $flag = true;
        foreach ($mixRuleArr as $_k => $_v){
            if(!array_key_exists($_k,$cis) || $cis[$_k] == 0){
                $flag = false;
                break;
            }
            $re[] = (int)floor($cis[$_k] / intval($_v));
        }
        if(!$flag) return 0;
        return min($re);
    }
}